---
title: 在 Astro 组件中共享状态
description: 了解如何通过 Nano Stores 在 Astro 组件中共享状态。
i18nReady: true
type: recipe
---
import { Steps } from '@astrojs/starlight/components';
import PackageManagerTabs from '~/components/tabs/PackageManagerTabs.astro';

:::tip
想使用框架组件？请参考 [如何在群岛间共享状态](/zh-cn/recipes/sharing-state-islands/)。
:::

在构建 Astro 网站时，你可能需要在组件之间共享状态。Astro 推荐使用 [Nano Stores](https://github.com/nanostores/nanostores) 来进行客户端的存储共享。

## 操作步骤

<Steps>
1. 安装 Nano Stores:

    <PackageManagerTabs>
      <Fragment slot="npm">
      ```shell
      npm install nanostores
      ```
      </Fragment>
      <Fragment slot="pnpm">
      ```shell
      pnpm add nanostores
      ```
      </Fragment>
      <Fragment slot="yarn">
      ```shell
      yarn add nanostores
      ```
      </Fragment>
    </PackageManagerTabs>

2.  创建一个存储（store）。在这个例子中，该存储用于跟踪对话框是否打开：

    ```ts title="src/store.js"
    import { atom } from 'nanostores';

    export const isOpen = atom(false);
    ```

3. 在要共享状态的组件的 `<script>` 标签中导入并使用存储。

    如下的 `Button` and `Dialog` 组件分别使用了共享的 `isOpen` 状态来控制特定的 `<div>` 元素是否隐藏或显示：

    ```astro title="src/components/Button.astro"
    <button id="openDialog">Open</button>

    <script>
      import { isOpen } from '../store.js';
      
      // 当按钮被点击时将状态设置为 true
      function openDialog() {
        isOpen.set(true);
      }

      // 为按钮添加一个事件监听器
      document.getElementById('openDialog').addEventListener('click', openDialog);
    </script>
    ```

    ```astro title="src/components/Dialog.astro"
    <div id="dialog" style="display: hidden">Hello world!</div>

    <script>
      import { isOpen } from '../store.js';

      // 监听状态的修改并相应地显示（或隐藏）对话框
      isOpen.subscribe(open => {
        if (open) {
          document.getElementById('dialog').style.display = 'block';
        } else {
          document.getElementById('dialog').style.display = 'none';
        }
      })
    </script>
    ```
</Steps>

## 资源

- [NPM 上的 Nano Stores 包](https://www.npmjs.com/package/nanostores)
- [Nano Stores 关于 JS 的文档](https://github.com/nanostores/nanostores#vanilla-js)
